home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / iso2022_kr.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  4.4 KB  |  199 lines

  1.  
  2. /*
  3.  * ISO-2022-KR
  4.  */
  5.  
  6. /* Specification: RFC 1557 */
  7.  
  8. /* Note: CJK.INF says the SO designator needs to appear only once at the
  9.    beginning of a text, but to decrease the risk of ambiguities, when
  10.    producing ISO-2022-KR, we repeat the designator in every line containing
  11.    SO characters. RFC 1557 does not mandate this. */
  12.  
  13. #define ESC 0x1b
  14. #define SO  0x0e
  15. #define SI  0x0f
  16.  
  17. /*
  18.  * The state is composed of one of the following values
  19.  */
  20. #define STATE_ASCII          0
  21. #define STATE_TWOBYTE        1
  22. /*
  23.  * and one of the following values, << 8
  24.  */
  25. #define STATE2_NONE                0
  26. #define STATE2_DESIGNATED_KSC5601  1
  27.  
  28. #define SPLIT_STATE \
  29.   unsigned int state1 = state & 0xff, state2 = state >> 8
  30. #define COMBINE_STATE \
  31.   state = (state2 << 8) | state1
  32.  
  33. static int
  34. iso2022_kr_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  35. {
  36.   state_t state = conv->istate;
  37.   SPLIT_STATE;
  38.   int count = 0;
  39.   unsigned char c;
  40.   for (;;) {
  41.     c = *s;
  42.     if (c == ESC) {
  43.       if (n < count+4)
  44.         goto none;
  45.       if (s[1] == '$') {
  46.         if (s[2] == ')') {
  47.           if (s[3] == 'C') {
  48.             state2 = STATE2_DESIGNATED_KSC5601;
  49.             s += 4; count += 4;
  50.             if (n < count+1)
  51.               goto none;
  52.             continue;
  53.           }
  54.         }
  55.       }
  56.       return RET_ILSEQ;
  57.     }
  58.     if (c == SO) {
  59.       if (state2 != STATE2_DESIGNATED_KSC5601)
  60.         return RET_ILSEQ;
  61.       state1 = STATE_TWOBYTE;
  62.       s++; count++;
  63.       if (n < count+1)
  64.         goto none;
  65.       continue;
  66.     }
  67.     if (c == SI) {
  68.       state1 = STATE_ASCII;
  69.       s++; count++;
  70.       if (n < count+1)
  71.         goto none;
  72.       continue;
  73.     }
  74.     break;
  75.   }
  76.   switch (state1) {
  77.     case STATE_ASCII:
  78.       if (c < 0x80) {
  79.         int ret = ascii_mbtowc(conv,pwc,s,1);
  80.         if (ret == RET_ILSEQ)
  81.           return RET_ILSEQ;
  82.         if (ret != 1) abort();
  83. #if 0 /* Accept ISO-2022-KR according to CJK.INF. */
  84.         if (*pwc == 0x000a || *pwc == 0x000d)
  85.           state2 = STATE2_NONE;
  86. #endif
  87.         COMBINE_STATE;
  88.         conv->istate = state;
  89.         return count+1;
  90.       } else
  91.         return RET_ILSEQ;
  92.     case STATE_TWOBYTE:
  93.       if (n < count+2)
  94.         goto none;
  95.       if (state2 != STATE2_DESIGNATED_KSC5601) abort();
  96.       if (s[0] < 0x80 && s[1] < 0x80) {
  97.         int ret = ksc5601_mbtowc(conv,pwc,s,2);
  98.         if (ret == RET_ILSEQ)
  99.           return RET_ILSEQ;
  100.         if (ret != 2) abort();
  101.         COMBINE_STATE;
  102.         conv->istate = state;
  103.         return count+2;
  104.       } else
  105.         return RET_ILSEQ;
  106.     default: abort();
  107.   }
  108.  
  109. none:
  110.   COMBINE_STATE;
  111.   conv->istate = state;
  112.   return RET_TOOFEW(count);
  113. }
  114.  
  115. static int
  116. iso2022_kr_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  117. {
  118.   state_t state = conv->ostate;
  119.   SPLIT_STATE;
  120.   unsigned char buf[2];
  121.   int ret;
  122.  
  123.   /* Try ASCII. */
  124.   ret = ascii_wctomb(conv,buf,wc,1);
  125.   if (ret != RET_ILSEQ) {
  126.     if (ret != 1) abort();
  127.     if (buf[0] < 0x80) {
  128.       int count = (state1 == STATE_ASCII ? 1 : 2);
  129.       if (n < count)
  130.         return RET_TOOSMALL;
  131.       if (state1 != STATE_ASCII) {
  132.         r[0] = SI;
  133.         r += 1;
  134.         state1 = STATE_ASCII;
  135.       }
  136.       r[0] = buf[0];
  137.       if (wc == 0x000a || wc == 0x000d)
  138.         state2 = STATE2_NONE;
  139.       COMBINE_STATE;
  140.       conv->ostate = state;
  141.       return count;
  142.     }
  143.   }
  144.  
  145.   /* Try KS C 5601-1992. */
  146.   ret = ksc5601_wctomb(conv,buf,wc,2);
  147.   if (ret != RET_ILSEQ) {
  148.     if (ret != 2) abort();
  149.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  150.       int count = (state2 == STATE2_DESIGNATED_KSC5601 ? 0 : 4) + (state1 == STATE_TWOBYTE ? 0 : 1) + 2;
  151.       if (n < count)
  152.         return RET_TOOSMALL;
  153.       if (state2 != STATE2_DESIGNATED_KSC5601) {
  154.         r[0] = ESC;
  155.         r[1] = '$';
  156.         r[2] = ')';
  157.         r[3] = 'C';
  158.         r += 4;
  159.         state2 = STATE2_DESIGNATED_KSC5601;
  160.       }
  161.       if (state1 != STATE_TWOBYTE) {
  162.         r[0] = SO;
  163.         r += 1;
  164.         state1 = STATE_TWOBYTE;
  165.       }
  166.       r[0] = buf[0];
  167.       r[1] = buf[1];
  168.       COMBINE_STATE;
  169.       conv->ostate = state;
  170.       return count;
  171.     }
  172.   }
  173.  
  174.   return RET_ILSEQ;
  175. }
  176.  
  177. static int
  178. iso2022_kr_reset (conv_t conv, unsigned char *r, int n)
  179. {
  180.   state_t state = conv->ostate;
  181.   SPLIT_STATE;
  182.   (void)state2;
  183.   if (state1 != STATE_ASCII) {
  184.     if (n < 1)
  185.       return RET_TOOSMALL;
  186.     r[0] = SI;
  187.     /* conv->ostate = 0; will be done by the caller */
  188.     return 1;
  189.   } else
  190.     return 0;
  191. }
  192.  
  193. #undef COMBINE_STATE
  194. #undef SPLIT_STATE
  195. #undef STATE2_DESIGNATED_KSC5601
  196. #undef STATE2_NONE
  197. #undef STATE_TWOBYTE
  198. #undef STATE_ASCII
  199.